feat: Redis,Valkey,MSSQL#10
Conversation
📝 WalkthroughWalkthroughThis PR refactors the CLI's database configuration flows to use interactive questionary-based prompts, adds support for additional database engines (Redis, Valkey, MSSQL), updates all Docker Compose service templates with healthchecks and standardized networking, and introduces secure password generation and styled prompts as core utilities. ChangesInteractive Database Configuration & Service Definition Updates
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
commands/agent.py (1)
316-356:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid persisting
type: "mysql"when provisioning a MariaDB container.Line 316 provisions only
AGENT_MARIADB_SNIPPET/db-mariadb-*, but Line 346 stores"type": db_engine. If user selectsmysql, metadata says MySQL while runtime is MariaDB, which can break downstream engine-specific handling.Suggested fix (normalize stored type to actual provisioned engine)
- elif db_engine == "mariadb" or db_engine == "mysql": + elif db_engine in {"mariadb", "mysql"}: mysql_port = get_free_port() db_user = "admin" db_pass = generate_password(16) db_name = f"mysql_{secrets.token_hex(4)}" service_name = f"db-mariadb-{secrets.token_hex(2)}" @@ add_db_to_json( path, { "name": db_name, "database": db_name, - "type": db_engine, + "type": "mariadb", "username": db_user, "password": db_pass, "port": 3306, "host": service_name, "generated_id": str(uuid.uuid4()), }, )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@commands/agent.py` around lines 316 - 356, The metadata written by add_db_to_json uses the original db_engine variable which can be "mysql" even though you provision AGENT_MARIADB_SNIPPET (MariaDB); change the stored type to reflect the actual provisioned engine by computing a concrete value (e.g., set actual_engine = "mariadb" when db_engine in ("mariadb","mysql")) and use that actual_engine in the add_db_to_json call (replace "type": db_engine with "type": actual_engine); locate the block that creates service_name/var_prefix/mysql_port and updates volumes_list and modify the add_db_to_json call there to pass the normalized engine string.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CITATION.cff`:
- Line 26: The CITATION.cff's date-released ("date-released: \"2026-04-20\"")
does not reflect the new features in this PR; update the date-released value to
the actual release date for this change or bump the version field (e.g., change
version from 26.04.1 to 26.04.2 or 26.05.x) and set date-released to the new
release date so the CITATION.cff accurately matches the new version and release
timestamp.
In `@commands/agent.py`:
- Around line 174-188: The default port selection for the IntPrompt.ask call
uses a nested ternary that falls through to 27017 (MongoDB) for unknown types,
which incorrectly assigns MongoDB's port to redis/valkey; update the default
expression used when constructing port (the IntPrompt.ask call) to explicitly
return 6379 when db_type is "redis" or "valkey" (place this check before the
final else/fallback), so the mapping handles "postgresql", "firebird", "mssql",
"mysql"/"mariadb", "redis"/"valkey" and then the remaining fallback.
In `@commands/db.py`:
- Around line 208-247: The sqlite branch (when db_engine == "sqlite") finishes
composing the sqlite file, calling add_db_to_json and printing success, but then
falls through into the subsequent non-sqlite compose-manipulation code that uses
snippet and service_name and corrupts docker-compose.yml; fix by inserting an
early continue (or otherwise short-circuit) immediately after the sqlite
handling block (after the console.print and add_db_to_json calls) so the loop
restarts and the later snippet/service_name logic is not executed for sqlite, or
alternatively wrap the later compose-manipulation logic in an explicit if
db_engine != "sqlite" guard to prevent the malformed volume insertion.
In `@pyproject.toml`:
- Around line 12-15: Remove the duplicate pyyaml dependency entry in the
dependency list in pyproject.toml by deleting the older "pyyaml >=6.0.0" line
and keeping only "pyyaml>=6.0.3"; ensure the dependencies array contains a
single pyyaml entry ("pyyaml>=6.0.3") to avoid ambiguity.
In `@templates/compose.py`:
- Around line 37-41: The healthcheck CMD-SHELL invocations use unquoted
${PASSWORD} which can be interpreted by the shell if the generated password
contains special characters; update each healthcheck test that calls
["CMD-SHELL", "mariadb-admin ping -h localhost -u ${USER} -p${PASSWORD}"]
(occurrences near healthcheck blocks using CMD-SHELL) to quote the password so
the shell receives it literally (e.g., -p"${PASSWORD}"), ensuring the quotes
wrap only the variable and preserving other arguments.
- Around line 198-200: The current healthcheck under the healthcheck block uses
a brittle /proc/net/tcp6 grep pattern; replace healthcheck.test with a stable
readiness probe that actually verifies MSSQL is accepting connections (for
example use a TCP port check like "CMD-SHELL", "nc -z localhost 1433" or a
proper SQL readiness command using sqlcmd: "CMD-SHELL", "bash -c 'until
/opt/mssql-tools/bin/sqlcmd -S localhost -U \"$MSSQL_USER\" -P
\"$MSSQL_PASSWORD\" -Q \"SELECT 1\" >/dev/null 2>&1; do sleep 1; done'"). Ensure
you update the healthcheck.interval as needed and keep the change scoped to the
healthcheck.test entry so the container reports healthy only when MSSQL
responds.
---
Outside diff comments:
In `@commands/agent.py`:
- Around line 316-356: The metadata written by add_db_to_json uses the original
db_engine variable which can be "mysql" even though you provision
AGENT_MARIADB_SNIPPET (MariaDB); change the stored type to reflect the actual
provisioned engine by computing a concrete value (e.g., set actual_engine =
"mariadb" when db_engine in ("mariadb","mysql")) and use that actual_engine in
the add_db_to_json call (replace "type": db_engine with "type": actual_engine);
locate the block that creates service_name/var_prefix/mysql_port and updates
volumes_list and modify the add_db_to_json call there to pass the normalized
engine string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ef5659c0-d92d-4b92-b224-3621d57edeb2
📒 Files selected for processing (10)
.github/assets/templates/agent.yml.github/assets/templates/dashboard.ymlCITATION.cffcommands/agent.pycommands/dashboard.pycommands/db.pycore/utils.pymain.pypyproject.tomltemplates/compose.py
📜 Review details
🧰 Additional context used
🪛 Ruff (0.15.13)
main.py
[warning] 25-25: Boolean-typed positional argument in function definition
(FBT001)
commands/db.py
[warning] 155-155: Unnecessary else after break statement
Remove unnecessary else
(RET508)
core/utils.py
[warning] 70-71: Replace if statement with length = max(length, 8)
Replace with length = max(length, 8)
(PLR1730)
commands/agent.py
[warning] 209-209: Unnecessary else after break statement
Remove unnecessary else
(RET508)
[warning] 316-316: Consider merging multiple comparisons: db_engine in {"mariadb", "mysql"}.
Merge multiple comparisons
(PLR1714)
🔇 Additional comments (8)
commands/db.py (3)
1-34: LGTM!
77-154: LGTM!
401-414: No action needed. Thegenerate_password(16)function explicitly ensures passwords include at least one character from each of four categories: lowercase, uppercase, digits, and special characters. This exceeds MSSQL's complexity requirement of at least three categories, so password generation is compliant.> Likely an incorrect or invalid review comment.main.py (1)
9-12: LGTM!Also applies to: 25-35, 40-82
commands/dashboard.py (1)
5-22: LGTM!Also applies to: 52-54, 56-77, 78-128, 137-150, 176-183
core/utils.py (1)
6-9: LGTM!Also applies to: 15-26, 68-90
.github/assets/templates/agent.yml (1)
2-3: LGTM!Also applies to: 8-12, 23-23
.github/assets/templates/dashboard.yml (1)
3-43: LGTM!Also applies to: 45-46
| license: Apache-2.0 | ||
| version: 26.04.1 | ||
| date-released: "2026-04-20" No newline at end of file | ||
| date-released: "2026-04-20" |
There was a problem hiding this comment.
❓ Verification inconclusive
Script executed:
#!/bin/bash
# Description: Check if version 26.04.1 was already tagged/released
# Check for existing git tags matching this version
git tag -l "*26.04.1*"
# Check git log for any commits related to this version
git log --all --grep="26.04.1" --onelineRepository: Portabase/cli
Repository: Portabase/cli
Exit code: 0
stdout:
5889f36 chore(release): 26.04.1
Script executed:
# Read the CITATION.cff file to see the full structure
cat CITATION.cffRepository: Portabase/cli
Repository: Portabase/cli
Exit code: 0
stdout:
cff-version: 1.0.0
title: Portabase CLI
message: "If you use this software, please cite it as below."
type: software
authors:
- family-names: Gauthereau
given-names: Charles
- family-names: Larcher
given-names: Killian
repository-code: https://github.com/Portabase/cli
url: https://portabase.io
abstract: "Portabase CLI is a command-line interface tool designed to streamline and enhance the management of Portabase services, providing developers with efficient access to core functionalities directly from the terminal."
keywords:
- portabase
- cli
- command-line
- tool
- developer
- productivity
- automation
- database
- management
- integration
license: Apache-2.0
version: 26.04.1
date-released: "2026-04-20"
Script executed:
# Check the git history of CITATION.cff to understand recent changes
git log --oneline -20 -- CITATION.cffRepository: Portabase/cli
Repository: Portabase/cli
Exit code: 0
stdout:
be843f7 add: mssql,more complex password
Script executed:
# Check when the release commit was made relative to this PR
git log --all --format="%h %ai %s" | grep -E "(release|CITATION)" | head -15Repository: Portabase/cli
Repository: Portabase/cli
Exit code: 0
stdout:
5889f36 2026-04-20 12:16:33 +0200 chore(release): 26.04.1
01b59a9 2026-02-17 08:10:16 +0100 chore(release): 26.02.17
b7d0621 2026-02-10 14:05:32 +0100 chore(release): 26.02.6
338fcb5 2026-02-10 14:03:51 +0100 chore(release): 26.02.5
66ea8ca 2026-02-10 13:58:09 +0100 chore(release): 26.02.4
2d077f7 2026-02-10 13:54:27 +0100 chore(release): 26.02.3
feba7a9 2026-02-10 13:51:43 +0100 chore(release): 26.02.2
eb5a448 2026-02-10 13:49:19 +0100 chore(release): 26.02.1
6f9f4b8 2026-01-27 20:49:21 +0100 chore(release): 26.01.27
ed1d8cf 2026-01-27 20:17:43 +0100 chore(release): 26.01.27
f1a6f17 2026-01-27 19:58:28 +0100 chore(release): 26.01.27
246de2c 2026-01-27 19:50:45 +0100 chore(release): 26.01.27b1
dabf648 2026-01-15 16:24:49 +0100 chore(release): 26.01.9
8356aef 2026-01-15 16:24:21 +0100 chore(release): 26.01.8
88ce856 2026-01-15 16:22:22 +0100 chore(release): 26.01.7
Script executed:
# Get the current branch and recent commits
git log --oneline -5
# Get the git diff to see what was changed on line 26 of CITATION.cff
git diff HEAD -- CITATION.cff || git show HEAD:CITATION.cff 2>/dev/null | head -30Repository: Portabase/cli
Repository: Portabase/cli
Exit code: 0
stdout:
be843f7 add: mssql,more complex password
Script executed:
# Check if there's a staging area change
git diff --cached -- CITATION.cff || trueRepository: Portabase/cli
Repository: Portabase/cli
Exit code: 0
Update the release date if this version includes new features added after April 20, 2026.
The date-released field is set to "2026-04-20" for version 26.04.1, which matches the historical release timestamp. However, if this PR introduces new features (Redis, Valkey, MSSQL support, interactive configuration) after that date, the release should either use a new version number (e.g., 26.04.2 or 26.05.x) with the appropriate release date, or the date should be updated to reflect when the release will actually occur.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CITATION.cff` at line 26, The CITATION.cff's date-released ("date-released:
\"2026-04-20\"") does not reflect the new features in this PR; update the
date-released value to the actual release date for this change or bump the
version field (e.g., change version from 26.04.1 to 26.04.2 or 26.05.x) and set
date-released to the new release date so the CITATION.cff accurately matches the
new version and release timestamp.
| port = IntPrompt.ask( | ||
| "Port", | ||
| default=5432 | ||
| if db_type == "postgresql" | ||
| else ( | ||
| 3050 | ||
| if db_type == "firebird" | ||
| else ( | ||
| 1433 | ||
| if db_type == "mssql" | ||
| else ( | ||
| 3306 if db_type in ["mysql", "mariadb"] else 27017 | ||
| ) | ||
| ) | ||
| ), |
There was a problem hiding this comment.
Fix incorrect default port mapping for Redis/Valkey in existing DB mode.
For db_type == "redis" or db_type == "valkey", the current fallback default becomes 27017, which is MongoDB’s port. This can silently create broken configs if users accept defaults.
Suggested fix
- port = IntPrompt.ask(
- "Port",
- default=5432
- if db_type == "postgresql"
- else (
- 3050
- if db_type == "firebird"
- else (
- 1433
- if db_type == "mssql"
- else (
- 3306 if db_type in ["mysql", "mariadb"] else 27017
- )
- )
- ),
- )
+ default_ports = {
+ "postgresql": 5432,
+ "mysql": 3306,
+ "mariadb": 3306,
+ "mongodb": 27017,
+ "redis": 6379,
+ "valkey": 6379,
+ "firebird": 3050,
+ "mssql": 1433,
+ }
+ port = IntPrompt.ask("Port", default=default_ports.get(db_type, 5432))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@commands/agent.py` around lines 174 - 188, The default port selection for the
IntPrompt.ask call uses a nested ternary that falls through to 27017 (MongoDB)
for unknown types, which incorrectly assigns MongoDB's port to redis/valkey;
update the default expression used when constructing port (the IntPrompt.ask
call) to explicitly return 6379 when db_type is "redis" or "valkey" (place this
check before the final else/fallback), so the mapping handles "postgresql",
"firebird", "mssql", "mysql"/"mariadb", "redis"/"valkey" and then the remaining
fallback.
| if db_engine == "sqlite": | ||
| db_name = Prompt.ask("Database Name", default="local") | ||
| if not db_name.endswith(".sqlite"): | ||
| db_name += ".sqlite" | ||
|
|
||
| compose_path = path / "docker-compose.yml" | ||
| if compose_path.exists(): | ||
| content = compose_path.read_text() | ||
| lines = content.splitlines(keepends=True) | ||
| new_lines = [] | ||
| in_app_service = False | ||
| inserted = False | ||
|
|
||
| for line in lines: | ||
| new_lines.append(line) | ||
| if not inserted: | ||
| if re.search(r"^ app:", line): | ||
| in_app_service = True | ||
| elif in_app_service and re.search(r"^ volumes:", line): | ||
| new_lines.append( | ||
| f" - ./{db_name}:/config/{db_name}\n" | ||
| ) | ||
| in_app_service = False | ||
| inserted = True | ||
| elif in_app_service and re.search(r"^ [a-zA-Z]", line): | ||
| in_app_service = False | ||
|
|
||
| with open(compose_path, "w") as f: | ||
| f.writelines(new_lines) | ||
|
|
||
| add_db_to_json( | ||
| path, | ||
| { | ||
| "name": db_name, | ||
| "database": f"/config/{db_name}", | ||
| "type": "sqlite", | ||
| "generated_id": str(uuid.uuid4()), | ||
| }, | ||
| ) | ||
| console.print(f"[success]✔ Added SQLite database ({db_name})[/success]") |
There was a problem hiding this comment.
Missing early exit corrupts compose file for SQLite.
When db_engine == "sqlite", this block handles compose modification and calls add_db_to_json, but then falls through to lines 416-453 which execute with snippet="" and service_name="". This results in:
- Line 430 inserting an extra newline
- Line 434 creating
vol_entry = " -data:\n"(malformed volume entry) - Lines 436-450 adding this malformed entry to the compose file
Add a continue after line 247 to restart the loop (allowing "back" navigation) or restructure to skip the non-sqlite compose manipulation.
🐛 Proposed fix
add_db_to_json(
path,
{
"name": db_name,
"database": f"/config/{db_name}",
"type": "sqlite",
"generated_id": str(uuid.uuid4()),
},
)
console.print(f"[success]✔ Added SQLite database ({db_name})[/success]")
+ break
elif db_engine == "postgresql":🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@commands/db.py` around lines 208 - 247, The sqlite branch (when db_engine ==
"sqlite") finishes composing the sqlite file, calling add_db_to_json and
printing success, but then falls through into the subsequent non-sqlite
compose-manipulation code that uses snippet and service_name and corrupts
docker-compose.yml; fix by inserting an early continue (or otherwise
short-circuit) immediately after the sqlite handling block (after the
console.print and add_db_to_json calls) so the loop restarts and the later
snippet/service_name logic is not executed for sqlite, or alternatively wrap the
later compose-manipulation logic in an explicit if db_engine != "sqlite" guard
to prevent the malformed volume insertion.
| if db_engine != "sqlite": | ||
| write_env_file(path, env_vars) | ||
| add_db_to_json( | ||
| path, | ||
| { | ||
| "name": "mirror.fdb" if db_engine == "firebird" else db_name, | ||
| "database": db_container_path | ||
| if db_engine == "firebird" | ||
| else ("0" if db_engine in ["redis", "valkey"] else db_name), | ||
| "type": db_engine, | ||
| "username": "sa" if db_engine == "mssql" else db_user, | ||
| "password": db_pass, | ||
| "port": 5432 | ||
| if db_engine == "postgresql" | ||
| else ( | ||
| 3050 | ||
| if db_engine == "firebird" | ||
| else ( | ||
| 3306 | ||
| if db_engine in ["mysql", "mariadb"] | ||
| else ( | ||
| 1433 | ||
| if db_engine == "mssql" | ||
| else ( | ||
| 6379 if db_engine in ["redis", "valkey"] else 27017 | ||
| ) | ||
| ) | ||
| ) | ||
| ), | ||
| "host": service_name, | ||
| "generated_id": str(uuid.uuid4()), | ||
| }, | ||
| ) | ||
| break |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoff
Clarify control flow by moving this block inside the else branch.
The if db_engine != "sqlite": block and final break are at the same indentation as the else: on line 155, placing them outside the else block. While this currently works because the "existing" mode breaks at line 154, the structure is confusing—this code is logically part of "new" mode only.
Consider either:
- Indenting lines 455-488 to be inside the
else:block - Restructuring to use early returns or separate functions for each mode
This also addresses the Ruff hint about "unnecessary else after break" at line 155.
| "pyyaml >=6.0.0", | ||
| "questionary>=2.1.0", | ||
| "pyyaml>=6.0.3" | ||
| ] |
There was a problem hiding this comment.
Remove the duplicate pyyaml requirement.
Line 12 and Line 14 declare pyyaml twice; keep only pyyaml>=6.0.3 to avoid ambiguous dependency maintenance.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pyproject.toml` around lines 12 - 15, Remove the duplicate pyyaml dependency
entry in the dependency list in pyproject.toml by deleting the older "pyyaml
>=6.0.0" line and keeping only "pyyaml>=6.0.3"; ensure the dependencies array
contains a single pyyaml entry ("pyyaml>=6.0.3") to avoid ambiguity.
| healthcheck: | ||
| test: ["CMD-SHELL", "mariadb-admin ping -h localhost -u ${USER} -p${PASSWORD}"] | ||
| interval: 10s | ||
| timeout: 5s | ||
| retries: 5 |
There was a problem hiding this comment.
Quote ${PASSWORD} in CMD-SHELL healthchecks.
Line 38, Line 141, and Line 179 pass ${PASSWORD} unquoted in shell commands. With generated symbols (&, |, etc.), healthchecks can fail or execute unintended shell parsing.
Suggested patch
- test: ["CMD-SHELL", "mariadb-admin ping -h localhost -u ${USER} -p${PASSWORD}"]
+ test: ["CMD-SHELL", "mariadb-admin ping -h localhost -u ${USER} -p'${PASSWORD}'"]
- test: ["CMD-SHELL", "redis-cli -a ${PASSWORD} ping | grep PONG"]
+ test: ["CMD-SHELL", "redis-cli -a '${PASSWORD}' ping | grep PONG"]
- test: ["CMD-SHELL", "valkey-cli -a ${PASSWORD} ping | grep PONG"]
+ test: ["CMD-SHELL", "valkey-cli -a '${PASSWORD}' ping | grep PONG"]Also applies to: 140-142, 178-180
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@templates/compose.py` around lines 37 - 41, The healthcheck CMD-SHELL
invocations use unquoted ${PASSWORD} which can be interpreted by the shell if
the generated password contains special characters; update each healthcheck test
that calls ["CMD-SHELL", "mariadb-admin ping -h localhost -u ${USER}
-p${PASSWORD}"] (occurrences near healthcheck blocks using CMD-SHELL) to quote
the password so the shell receives it literally (e.g., -p"${PASSWORD}"),
ensuring the quotes wrap only the variable and preserving other arguments.
| healthcheck: | ||
| test: ["CMD-SHELL", "cat /proc/net/tcp6 | grep -q '059901' || exit 1"] | ||
| interval: 10s |
There was a problem hiding this comment.
Replace the MSSQL healthcheck probe with a stable readiness check.
Line 199 relies on parsing /proc/net/tcp6 with a hardcoded pattern (059901), which is brittle and can keep the service unhealthy despite successful startup.
Suggested direction
- test: ["CMD-SHELL", "cat /proc/net/tcp6 | grep -q '059901' || exit 1"]
+ test: ["CMD-SHELL", "nc -z localhost 1433 || exit 1"]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| healthcheck: | |
| test: ["CMD-SHELL", "cat /proc/net/tcp6 | grep -q '059901' || exit 1"] | |
| interval: 10s | |
| healthcheck: | |
| test: ["CMD-SHELL", "nc -z localhost 1433 || exit 1"] | |
| interval: 10s |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@templates/compose.py` around lines 198 - 200, The current healthcheck under
the healthcheck block uses a brittle /proc/net/tcp6 grep pattern; replace
healthcheck.test with a stable readiness probe that actually verifies MSSQL is
accepting connections (for example use a TCP port check like "CMD-SHELL", "nc -z
localhost 1433" or a proper SQL readiness command using sqlcmd: "CMD-SHELL",
"bash -c 'until /opt/mssql-tools/bin/sqlcmd -S localhost -U \"$MSSQL_USER\" -P
\"$MSSQL_PASSWORD\" -Q \"SELECT 1\" >/dev/null 2>&1; do sleep 1; done'"). Ensure
you update the healthcheck.interval as needed and keep the change scoped to the
healthcheck.test entry so the container reports healthy only when MSSQL
responds.
Summary by CodeRabbit
New Features
Improvements